<?php

namespace App\Models\Traits;

use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
use Rainsens\Dinglog\Facades\Dinglog;
use Brick\Math\RoundingMode;
use Carbon\Carbon;

trait HasUserCache
{
	public static function sMyPayCodeTryCacheKey($id): string
	{
		return "user_{$id}_pay_code_try";
	}

	public static function sInfoCacheKey($id): string
	{
		return "user_{$id}_info";
	}

	public static function sGetCache($id)
	{
		if (! Redis::exists(self::sInfoCacheKey($id))) {
			if ($user = self::find($id)) {
				$user->addToCache();
				$user->setRank();
				Log::debug("User: {$user->id} first cached");
			}
		}
		return Redis::hGetAll(self::sInfoCacheKey($id));
	}



	/*==================================================================================================================*/


	public function myPayCodeTryCacheKey(): string
	{
		return self::sMyPayCodeTryCacheKey($this->id);
	}

	public function infoCacheKey(): string
	{
		return self::sInfoCacheKey($this->id);
	}

	public function cacheFields(): array
	{
        $user = $this;
        $parent = "";
       
      
		return [
			'id' => $user->id,
			'name' => $user->name ?? '',
			'nickname' => $user->nickname ?? '',
			'phone' => $user->phone ?? '',
			'signature' => $user->signature ?? '',
			'avatar_url' => img_path($user->avatar),
			'gender' => $user->gender ?? '',
			'birthday' => $user->birthday ?? '',
			'is_locked' => $user->is_locked ?? 0,
			'xhs_num' =>  $user->xhs_num ?? 0,
			'dy_num' =>  $user->dy_num ?? 0,
			'sph_num' =>  $user->sph_num ?? 0,
			'ks_num' =>  $user->ks_num ?? 0,
			'xhs_fans' =>  $user->xhs_fans ?? 0,
			'dy_fans' =>  $user->dy_fans ?? 0,
			'ks_fans' =>  $user->ks_fans ?? 0,
			'sph_fans' =>  $user->sph_fans ?? 0,
			'fyb_num' =>  $user->fyb_num ?? 0,
			'fyb_fans' =>  $user->fyb_fans ?? 0,

			'yesterday_xhs_fans' =>  !empty($user->userFans()->where('gc_type','xhs')->whereDate('created_at',Carbon::today())->sum('money')) ? intval($user->userFans()->where('gc_type','xhs')->whereDate('created_at',Carbon::today())->sum('money')) : '',
			'yesterday_dy_fans' => !empty($user->userFans()->where('gc_type','dy')->whereDate('created_at',Carbon::today())->sum('money')) ? intval($user->userFans()->where('gc_type','dy')->whereDate('created_at',Carbon::today())->sum('money')) : '',
			'yesterday_sph_fans' => !empty($user->userFans()->where('gc_type','sph')->whereDate('created_at',Carbon::today())->sum('money')) ? intval($user->userFans()->where('gc_type','sph')->whereDate('created_at',Carbon::today())->sum('money')) : '',
			'yesterday_ks_fans' => !empty($user->userFans()->where('gc_type','ks')->whereDate('created_at',Carbon::today())->sum('money')) ? intval($user->userFans()->where('gc_type','ks')->whereDate('created_at',Carbon::today())->sum('money')) : '',
			'yesterday_fyb_fans' => !empty($user->userFans()->where('gc_type','fyb')->whereDate('created_at',Carbon::today())->sum('money')) ? intval($user->userFans()->where('gc_type','fyb')->whereDate('created_at',Carbon::today())->sum('money')) : '',
			'created_at' => (string)$user->created_at,
			
		];
	}

	public function addToCache()
	{
		$data = $this->cacheFields();

		//Redis::transaction(function () use ($data) {
			Redis::hMSet($this->infoCacheKey(), $data);
			Redis::expire($this->infoCacheKey(), cache_time());
		//});

			
	}

	public function addToRank()
	{
		$yesterdayAllMoney = (string)big_decimal($this->myDownChildrenRewardYesterday())->plus($this->resoldProfitYesterday());
		$dividendAllMoney = (string)big_decimal($this->resoldProfitAll())->plus($this->myDownChildrenReward());

		Redis::zAdd('yesterday_rank',$yesterdayAllMoney,$this->id);
		Redis::zAdd('dividend_rank',$dividendAllMoney,$this->id);

		Redis::hMset($this->infoCacheKey(), ['dividend_all_money'=>$dividendAllMoney,'yesterday_all_money'=>$yesterdayAllMoney]);
	}

	public function setRank()
	{
		$yesterdayRankCache = Redis::Zrevrank("yesterday_rank",$this->id);
		$dividentRankCache = Redis::Zrevrank("dividend_rank",$this->id);
     	Dinglog::text("设置rank");
     	if($yesterdayRankCache >= 0 && $this->is_gold_intern == 1){
     		$yesterdayRankCache = $yesterdayRankCache + 1;

     	}else{
     		$yesterdayRankCache = 0;

     	}
        

     	if($yesterdayRankCache > 100){

     		$yesterdayRankCache = 0;
     	}

     	if($dividentRankCache >= 0 && $this->is_gold_intern == 1){
     		$dividentRankCache = $dividentRankCache + 1;

     	}else{
     		$dividentRankCache = 0;

     	}
        

     	if($dividentRankCache > 100){

     		$dividentRankCache = 0;
     	}
     	$yesterdayAllMoney = (string)big_decimal($this->myDownChildrenRewardYesterday())->plus($this->resoldProfitYesterday());
		$dividendAllMoney = (string)big_decimal($this->resoldProfitAll())->plus($this->myDownChildrenReward());
		Redis::hMset($this->infoCacheKey(), ['yesterday_rank'=>$yesterdayRankCache,'dividend_rank'=>$dividentRankCache,'dividend_all_money'=>$dividendAllMoney,'yesterday_all_money'=>$yesterdayAllMoney]);
	}


	public function getCachePay()
	{
		if (! Redis::exists($this->infoCacheKey())) {
			$this->addToCache();
			$this->setRank();
		}
		$data = [
			'wx_image' => Redis::hGet($this->infoCacheKey(),'wx_image'),
			'alipay_real_name' => Redis::hGet($this->infoCacheKey(),'alipay_real_name'),
			'alipay_number' => Redis::hGet($this->infoCacheKey(),'alipay_number'),
			'real_name' => Redis::hGet($this->infoCacheKey(),'real_name'),
			'bank_name' => Redis::hGet($this->infoCacheKey(),'bank_name'),
			'bank_abbr' => Redis::hGet($this->infoCacheKey(),'bank_abbr'),
			'phone' => Redis::hGet($this->infoCacheKey(),'contact_phone'),
			'cert_number' => Redis::hGet($this->infoCacheKey(),'cert_number'),
			'avatar_url' =>  Redis::hGet($this->infoCacheKey(),'avatar_url'),
			'user_name' =>  Redis::hGet($this->infoCacheKey(),'name'),
		];
		
		return $data;
	}


	public function getBeansCache()
	{
		if (! Redis::exists($this->infoCacheKey())) {
			$this->addToCache();
			$this->setRank();
		}
		
		
		return Redis::hGet($this->infoCacheKey(),'gold_beans');
	}

	public function setGoldBeans($todayBeans)
	{
		$userBeans =Redis::hGet($this->infoCacheKey(),'gold_beans');
		$beans = big_decimal($userBeans)->minus($todayBeans);

		return Redis::hMset($this->infoCacheKey(),['gold_beans'=>(string)$beans]);
	}

	public function getCache()
	{
		
		//if (! Redis::exists($this->infoCacheKey())) {

			$this->addToCache();
			
			//$this->setRank();
		//}
		return Redis::hGetAll($this->infoCacheKey());
	}


	public function setNickName($nickname){
		Redis::hMSet($this->infoCacheKey(), ['nickname'=>$nickname]);

	}
	public function delFromCache()
	{
		Redis::del($this->infoCacheKey());
	}

	public function todayBonusTop100FromCache()
	{
		$key = "today_bonus_rank";
		return Cache::remember($key, 60, function () {
			return $this->dayBonusTop100();
		});
	}

	public function allBonusTop100FromCache()
	{
		$key = "all_bonus_rank";
		return Cache::remember($key, 60, function () {
			return $this->allBonusTop100();
		});
	}

	public function dayBonusRank($index = 0): array
	{
		$users = collect();

		$limit = $index + 9;
		$index = $index > 0 ? $index+1 : $index;

		$top100 = $this->todayBonusTop100FromCache();

		$mineId = $this->id;
		$mineRank = $top100->contains($mineId) ? $top100->search($mineId)+1 : 0;

		foreach ($top100 as $k => $id) {
			if ($k >= $index and $k <= $limit) {
				$users->push(self::sGetCache($id));
			}
		}

		return ['mine' => (int)$mineRank, 'day' => $users];
	}

	public function allBonusRank($index = 0): array
	{
		$users = collect();

		$limit = $index + 9;
		$index = $index > 0 ? $index+1 : $index;

		$top100 = $this->allBonusTop100FromCache();

		$mineId = $this->id;
		$mineRank = $top100->contains($mineId) ? $top100->search($mineId)+1 : 0;

		foreach ($top100 as $k => $id) {
			if ($k >= $index and $k <= $limit) {
				$users->push(self::sGetCache($id));
			}
		}

		return ['mine' => (int)$mineRank, 'all' => $users];
	}

	public function myTeamMembers()
	{
		$scope = request('scope');

		$key = url()->full();
		$key = "{$key}-user-{$this->id}-{$scope}-teams";

		return Cache::remember($key, 1, function () use ($scope) {
			return $this->myDownOneChildren($scope)
				->orderBy('parent_id')
				->orderByDesc('id')
				->paginate();
		});
	}

	public function myPayCodeTryCache(): int
	{
		$key = $this->myPayCodeTryCacheKey();

		if ($try = Redis::get($key)) {
			return (int)$try;
		} else {
			Redis::set($key, 0);
			$try = Redis::get($key);
			return (int)$try;
		}
	}

	public function leftPayCodeTryAfterError(): int
	{
		$payCodeTry = $this->myPayCodeTryCache() + 1;
		$payCodeTry = $payCodeTry <= 3 ? $payCodeTry : 3;
		Redis::set($this->myPayCodeTryCacheKey(), $payCodeTry);
		$leftChance = 3 - $payCodeTry;
		return $leftChance;
	}

	public function resetPayCodeTry()
	{
		$try = $this->myPayCodeTryCache();

		if ($try <= 0) return;

		Redis::set($this->myPayCodeTryCacheKey(), 0);
	}
}
